import { ComponentClass } from 'react'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, ScrollView, Text, Image } from '@tarojs/components'
import { connect } from '@tarojs/redux'

import { isTimeIntervalValid } from '../../utils/pagination'
import CollectionService from '../../services/collect'
import { Utils } from '../../utils/utils'
import { getNextPage } from '../../utils/pagination'
import {
  depositFilterOptions,
  timeFilterOptions,
  sortFilterOptions,
  productTypeOptions,
  mortgageTypeOptions,
  jobsOptions,
} from '../../config/index'

import ProductFilter from '../../components/product-filter'
import ProductList from '../../components/product-list'

import './index.scss'


// #region 书写注意
// 
// 目前 typescript 版本还无法在装饰器模式下将 Props 注入到 Taro.Component 中的 props 属性
// 需要显示声明 connect 的参数类型并通过 interface 的方式指定 Taro.Component 子类的 props
// 这样才能完成类型检查和 IDE 的自动提示
// 使用函数模式则无此限制
// ref: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20796
//
// #endregion

const collectionService = new CollectionService()
const utils = new Utils()

type PageStateProps = {
  productList: any[],
  effects: any,
  productLastLoadTime: number,
  userApplyList: any[],
  productNoneResult: boolean,
  productNoneResultTips: string,
  productPage: number,   // 当前收藏列表页
  defaultPageSize: number,  // 每页条数
  searchOption: any,
  searchCondition: any,
}

type PageDispatchProps = {
  dispatchsearchProduct: (param: any) => void,
  dispatchSearchUpdate: (param: any) => void,
  dispatchSave: (param: any) => void,
}

type PageOwnProps = {}

type PageState = {}

type IProps = PageStateProps & PageDispatchProps & PageOwnProps

interface ProductFilterList {
  props: IProps;
  state: PageState;
}

@connect(({ productFilterList, common, loading }) => ({
  ...productFilterList,
  ...common,
  ...loading,
}), (dispatch) => ({
  dispatchsearchProduct(param: any) {
    dispatch({
      type: 'productFilterList/searchProduct',
      payload: param,
    })
  },
  dispatchSearchUpdate(param: any) {
    dispatch({
      type: 'productFilterList/updateSearchCondition',
      payload: param,
    })
  },
  dispatchSave(param: any) {
    dispatch({
      type: 'productFilterList/save',
      payload: param
    })
  }
}))
/**
 * 产品过滤列表页组件
 */
class ProductFilterList extends Component {

  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(nextProps) {
    const that = this

    // 搜索条件改变的情况下，重新加载产品
    const nextSearchCondition = nextProps.searchCondition
    const currSearchCondition = that.props.searchCondition
    if (nextSearchCondition && currSearchCondition
      && JSON.stringify(nextSearchCondition) !== JSON.stringify(currSearchCondition)) {
      // 要异步dispatch， 否则小程序会有问题...
      setTimeout(() => {
        that._reloadProduct()
      }, 0)
    }
  }

  componentWillMount() {
    this.initSearchConditionByOptions()

    // this._reloadProduct()
  }

  componentDidMount() { }

  componentWillUnmount() { }

  componentDidShow() { }

  componentDidHide() { }

  render() {
    const { productList, userApplyList, 
      productNoneResult, productNoneResultTips, 
      searchOption } = this.props

    return (
      <View className='product-filter-list-container'>
        
        {/* 产品过滤组件分块 */}
        <View className='product-filter-box'>
          <ProductFilter inputOption={searchOption} dispatchActionType={'productFilterList/updateSearchCondition'} isNeedFixTop={false} scrollTop={0} />
        </View>

        <View className="product-list-box">
          <ScrollView
            scrollY
            scrollWithAnimation
            scrollTop={0}
            lowerThreshold={0}
            style='height: 93vh'
            onScrollToLower={this.onLoadMoreCollection.bind(this)}>
            
            <ProductList
              dataArray={productList}
              userApplyList={userApplyList}
              isShowCheck={false} isShowLoanTime={true} isShowApply={true} isShowCollectCancel={false}
              loading={this.props.effects['productFilterList/searchProduct']}
              noneResult={productNoneResult}
              noneResultTips={productNoneResultTips} />

          </ScrollView>
        </View>
      </View>
    )
  }

  /**
   * 滚动到底部触发，加载更多
   * @param e 
   */
  onLoadMoreCollection(e) {
    if (this.props.effects['productFilterList/searchProduct']) {
      // console.log('加载数据中，return !!!', e)
      return
    }
    if (!isTimeIntervalValid(this.props.productLastLoadTime)) {
      // console.log('太频繁了，return !!!', e)
      return
    }
    this._loadMoreProduct()
  }

  /**
   * 加载更多产品
   */
  _loadMoreProduct() {
    this.props.dispatchsearchProduct({
      ...this.props.searchCondition,
      page: getNextPage(this.props.productPage, this.props.defaultPageSize, this.props.productList.length)
    })
  }

  /**
   * 重新加载产品
   */
  _reloadProduct() {
    this.props.dispatchsearchProduct({
      ...this.props.searchCondition,
      page: 1
    })
  }

  /**
   * 根据url参数初始化查询条件
   */
  initSearchConditionByOptions() {
    
    let {
      deposit, time_limit, sort, product_type, mortgage_type, job, load_product_type,
    } = this.$router.params

    const { searchCondition, searchOption } = this.props

    const condition = Object.assign({}, searchCondition)
    condition.deposit = deposit || condition.deposit
    condition.time_limit = time_limit || condition.time_limit
    condition.sort = sort || condition.sort
    condition.product_type = product_type || condition.product_type
    condition.mortgage_type = mortgage_type || condition.mortgage_type
    condition.job = job || condition.job

    const option = Object.assign({}, searchOption)
    if (deposit > 0) {
      option.deposit = utils.getOptionByValue(parseInt(deposit), depositFilterOptions, 'value')
    } else {
      option.deposit = depositFilterOptions[0]
    }
    if (time_limit > 0) {
      option.time_limit = utils.getOptionByValue(parseInt(time_limit), timeFilterOptions, 'value')
    } else {
      option.time_limit = timeFilterOptions[0]
    }
    if (sort === '' || sort > 0) {
      if (sort > 0) {
        sort = parseInt(sort)
      }
      option.sort = utils.getOptionByValue(sort, sortFilterOptions, 'value')
    } else {
      option.sort = sortFilterOptions[0]
    }
    if (product_type === '' || product_type > 0) {
      if (product_type > 0) {
        product_type = parseInt(product_type)
      }
      option.product_type = utils.getOptionByValue(product_type, productTypeOptions, 'value')
    } else {
      option.product_type = productTypeOptions[0]
    }
    if (mortgage_type === '' || mortgage_type > 0) {
      if (mortgage_type > 0) {
        mortgage_type = parseInt(mortgage_type)
      }
      option.mortgage_type = utils.getOptionByValue(mortgage_type, mortgageTypeOptions, 'value')
    } else {
      option.mortgage_type = mortgageTypeOptions[0]
    }
    if (job === '' || job > 0) {
      if (job > 0) {
        job = parseInt(job)
      }
      option.job = utils.getOptionByValue(job, jobsOptions, 'value')
    } else {
      option.job = jobsOptions[0]
    }

    // 更新参数
    this.props.dispatchSearchUpdate({
      condition,
      option,
    })
    this.props.dispatchSave({
      loadProductType: load_product_type,
    })
  }
}
// #region 导出注意
//
// 经过上面的声明后需要将导出的 Taro.Component 子类修改为子类本身的 props 属性
// 这样在使用这个子类时 Ts 才不会提示缺少 JSX 类型参数错误
//
// #endregion

export default ProductFilterList as ComponentClass<PageOwnProps, PageState>
